package optimizers.commons.evaluator;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import javax.swing.SwingWorker;

import common.RunStatus;

import optimizers.commons.GAConstants;
import optimizers.ganeat.Individual;
import optimizers.ganeat.report.LoggerNEAT;

import fitness.Fitness;
import fitness.FitnessResult;

import model.OligoSystemComplex;
import model.OligoSystemGeneral;

public class TimeSeriesCalculationService {
	protected CompletionService<Object> cservice;
	protected ExecutorService eservice;
	protected int numberOfThreads = 8;
	protected int averageTime = 50;// GAConstants.maxExecutionInSeconds;
	LoggerNEAT logger;

	public TimeSeriesCalculationService() {
		eservice = Executors.newFixedThreadPool(numberOfThreads);
		cservice = new ExecutorCompletionService<Object>(eservice);
	}

	public double[][][] calculateTimeSeries(OligoSystemComplex[] oligoSystems) {
		double[][][] results = new double[oligoSystems.length][][];
		int taskCount = 0;
		ArrayList<Future<Object>> futures = new ArrayList<Future<Object>>();
		for (int i = 0; i < oligoSystems.length; i++) {
			futures.add(cservice.submit(new TimeSeriesCalculationTask(i,
					oligoSystems[i])));
			taskCount++;
		}

		for (int i = 0; i < taskCount; i++) {
			try {
				Future<Object> future = cservice.poll(this.averageTime,
						TimeUnit.SECONDS);

				if (future != null) {
					TimeSeriesCalculationResult result = (TimeSeriesCalculationResult) future
							.get();
					int index = result.index;
					results[index] = result.result;
				} else {
					System.out.println("Some evaluation is too slow");
					/*
					 * List<Runnable> remains = eservice.shutdownNow();
					 * logger.logToMemory(remains.size() + " remains");
					 * taskCount = i + remains.size(); futures = new
					 * ArrayList<Future<Object>>(); while
					 * (!eservice.awaitTermination(awaitTime, TimeUnit.SECONDS))
					 * ; logger.logToMemory("Service ended perfectly"); eservice
					 * = Executors.newFixedThreadPool(numberOfThreads); cservice
					 * = new ExecutorCompletionService<Object>(eservice); for
					 * (Runnable rem : remains) {
					 * futures.add(cservice.submit(rem, evaluator)); }
					 */
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return results;
	}
}
